package ui;

import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;

import javax.imageio.ImageIO;
import javax.swing.GroupLayout;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenuBar;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.ListSelectionModel;
import javax.swing.UIManager;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.GroupLayout.Alignment;
import javax.swing.table.DefaultTableModel;

import controller.EmployeeController;
import model.Employee;
import model.EmployeeJob;
import util.EmailValidator;
import util.ImagePanel;
import util.MD5;
import util.Menu;
import util.PdfFilePrint;

import javax.swing.LayoutStyle.ComponentPlacement;

public class EmployeeUI implements ActionListener
{
	private boolean startup = false;

	private static EmployeeUI instance = null;

	private EmployeeController employeeCtrl;
	private EmailValidator emailValidator;

	private JFrame frameEmployeeUI;

	private JTabbedPane tabbedPane;

	private ImagePanel newEmployee;
	private ImagePanel allEmployees;

	private JPanel redPanel;

	private Image image = null;
	private JTable allEmployeesTable;

	private DefaultTableModel allEmployeesTableModel;

	private JComboBox<String> allEmployeesComboBoxSearchType;
	private JComboBox<String> allEmployeesComboBoxSearchJobs;
	private JComboBox<String> newEmployeeComboBoxStatus;
	private JComboBox<String> newEmployeeComboBoxAccess;
	private JComboBox<String> editEmployeeComboBoxAccess;

	private JButton newEmployeeButtonCreateEmployee;
	private JButton allEmployeesButtonSearchClear;
	private JButton allEmployeesButtonEditEmployee;
	private JButton allEmployeesButtonDeactivateEmployee;
	private JButton statistics;
	private JButton btnPrint;

	private JCheckBox allEmployeesCheckBoxOnlyActiveEmployees;

	private JTextField allEmployeesTextFieldSearchFor;
	private JTextField newEmployeeTextFieldUsername;
	private JTextField newEmployeeTextFieldPhoneNo;
	private JTextField newEmployeeTextFieldEmail;
	private JTextField newEmployeeTextFieldLastName;
	private JTextField newEmployeeTextFieldFirstName;

	private JPasswordField newEmployeePasswordFieldSecond;
	private JPasswordField newEmployeePasswordFieldFirst;

	private ArrayList<JTextField> newEmployeeTextFields;
	private ArrayList<JTextField> editEmployeeTextFields;

	private ArrayList<JPasswordField> newEmployeePasswordFields;
	private ArrayList<JPasswordField> editEmployeePasswordFields;

	private ArrayList<EmployeeJob> jobList;

	private Menu menuBar;

	private JMenuBar menu;

	private backButton back;
	private JButton btnBack;


	public void display()
	{
		frameEmployeeUI.getContentPane().add(redPanel);

		tabbedPane.add("All Employees", allEmployees);
		tabbedPane.add("New Employee", newEmployee);

		frameEmployeeUI.setSize(800,420);
		frameEmployeeUI.setLocationRelativeTo(null);
		frameEmployeeUI.setVisible(true);
		frameEmployeeUI.setResizable(false);
	}

	public EmployeeUI()
	{
		back = new backButton();
		back.setNumber("7");

		frameEmployeeUI = new JFrame("Employee UI");

		menuBar = Menu.getInstance();

		menu = menuBar.makeJMenuBar();

		frameEmployeeUI.setJMenuBar(menu);

		redPanel = new JPanel();
		redPanel.setBackground(new Color(165, 42, 42));

		tabbedPane = new JTabbedPane();
		tabbedPane.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT);

		employeeCtrl = new EmployeeController();
		emailValidator = new EmailValidator();

		try
		{
			image = ImageIO.read(new File("img/background/background.jpg"));
		} 
		catch (IOException e)
		{
			msgError(null, "Could not load background image");
		}

		JLabel redPanelLabelTitle = new JLabel("EMPLOYEE MENU");
		redPanelLabelTitle.setForeground(Color.WHITE);
		redPanelLabelTitle.setFont(new Font("Arial Unicode MS", Font.BOLD, 20));

		statistics = new JButton();
		statistics.setOpaque(false);
		statistics.setText("Statistics");
		statistics.addActionListener(this);

		btnBack = new JButton();
		btnBack.addActionListener(this);
		btnBack.setText("Back");
		btnBack.setOpaque(false);

		/******************************************************
		 * 
		 * New employee pane
		 * 
		 ******************************************************/

		newEmployee = new ImagePanel(image);

		JLabel newEmployeeLabelName = new JLabel("Employee Username:");
		JLabel newEmployeeLabelPassword = new JLabel("Employee Password:");
		JLabel newEmployeeLabelPhoneno = new JLabel("Employee PhoneNo:");
		JLabel newEmployeeLabelEmail = new JLabel("Employee E-mail:");
		JLabel newEmployeeLabelStatus = new JLabel("Employee Status:");
		JLabel newEmployeeLabelFirstName = new JLabel("Employee First Name:");
		JLabel newEmployeeLabelLastName = new JLabel("Employee Last Name:");
		JLabel newEmployeeLabelAccess = new JLabel("Employee Access:");
		JLabel newEmployeeLabelPasswordAgain = new JLabel("Employee Password Again:");

		newEmployeeTextFieldUsername = new JTextField();
		newEmployeeTextFieldPhoneNo = new JTextField();
		newEmployeeTextFieldEmail = new JTextField();
		newEmployeeTextFieldLastName = new JTextField();
		newEmployeeTextFieldFirstName = new JTextField();

		newEmployeeComboBoxStatus = new JComboBox<String>();
		newEmployeeComboBoxStatus.addItem("Active");
		newEmployeeComboBoxStatus.addItem("Inactive");

		newEmployeeComboBoxAccess = new JComboBox<String>();

		newEmployeeButtonCreateEmployee = new JButton("Create Employee");
		newEmployeeButtonCreateEmployee.setOpaque(false);
		newEmployeeButtonCreateEmployee.addActionListener(this);

		newEmployeePasswordFieldSecond = new JPasswordField();
		newEmployeePasswordFieldFirst = new JPasswordField();

		newEmployeeTextFields = new ArrayList<JTextField>();
		newEmployeeTextFields.add(newEmployeeTextFieldUsername);
		newEmployeeTextFields.add(newEmployeeTextFieldPhoneNo);
		newEmployeeTextFields.add(newEmployeeTextFieldEmail);
		newEmployeeTextFields.add(newEmployeeTextFieldLastName);
		newEmployeeTextFields.add(newEmployeeTextFieldFirstName);

		newEmployeePasswordFields = new ArrayList<JPasswordField>();
		newEmployeePasswordFields.add(newEmployeePasswordFieldFirst);
		newEmployeePasswordFields.add(newEmployeePasswordFieldSecond);

		/******************************************************
		 * 
		 * All employees pane
		 * 
		 ******************************************************/

		allEmployees = new ImagePanel(image);

		String allEmployeesColumns [] = { "#", "First Name", "Last Name", "PhoneNo", "Email", "Job", "Username", "Active" };
		allEmployeesTableModel = new DefaultTableModel(null, allEmployeesColumns);

		allEmployeesTable = new JTable(allEmployeesTableModel)
		{
			private static final long serialVersionUID = 1L;

			public boolean isCellEditable(int rowIndex, int colIndex) 
			{
				return false;
			}

			public Class<?> getColumnClass(int column)   
			{   
				return getValueAt(0, column).getClass();   
			}  
		};

		Dimension dim = allEmployeesTable.getPreferredSize(); 
		double width = dim.width / allEmployeesColumns.length; 
		double[] width_2 = { 0.3, 1.2, 1.2, 1, 2, 1, 1, 1  };

		for (int i = 0; i < allEmployeesColumns.length; i++)
			allEmployeesTable.getColumnModel().getColumn(i).setPreferredWidth((int) (width*width_2[i])); 

		allEmployeesTable.setAutoCreateRowSorter(true);

		allEmployeesTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		JScrollPane allEmployeesTableScroll = new JScrollPane(allEmployeesTable);

		JLabel allEmployeesLabelSearchBy = new JLabel("Search by:");
		JLabel allEmployeesLabelSearchFor = new JLabel("Search for:");
		JLabel allEmployeesLabelSearchJobs = new JLabel("Search jobs:");

		allEmployeesComboBoxSearchJobs = new JComboBox<String>();
		allEmployeesComboBoxSearchJobs.setOpaque(false);
		allEmployeesComboBoxSearchJobs.addActionListener(this);
		allEmployeesComboBoxSearchJobs.addItem("All jobs");

		allEmployeesComboBoxSearchType = new JComboBox<String>();
		allEmployeesComboBoxSearchType.setOpaque(false);
		allEmployeesComboBoxSearchType.addActionListener(this);
		allEmployeesComboBoxSearchType.addItem("Everything");
		allEmployeesComboBoxSearchType.addItem("Name");
		allEmployeesComboBoxSearchType.addItem("Username");
		allEmployeesComboBoxSearchType.addItem("Email");
		allEmployeesComboBoxSearchType.addItem("PhoneNo");

		allEmployeesTextFieldSearchFor = new JTextField();
		allEmployeesTextFieldSearchFor.getDocument().addDocumentListener(new DocumentListener()
		{
			@Override
			public void insertUpdate(DocumentEvent e)
			{
				// most likely to never be used .. 
				searchEmployees();						
			}

			@Override
			public void changedUpdate(DocumentEvent e)
			{
				searchEmployees();
			}

			@Override
			public void removeUpdate(DocumentEvent e)
			{
				searchEmployees();
			}
		});

		allEmployeesButtonSearchClear = new JButton("Clear Search");
		allEmployeesButtonSearchClear.setOpaque(false);
		allEmployeesButtonSearchClear.addActionListener(this);

		allEmployeesButtonEditEmployee = new JButton("Edit Employee");
		allEmployeesButtonEditEmployee.setOpaque(false);
		allEmployeesButtonEditEmployee.addActionListener(this);

		allEmployeesButtonDeactivateEmployee = new JButton("Change Status");
		allEmployeesButtonDeactivateEmployee.setOpaque(false);
		allEmployeesButtonDeactivateEmployee.addActionListener(this);

		JLabel label = new JLabel("Vaizdine Reklama Software v0.1");
		label.setEnabled(false);

		allEmployeesCheckBoxOnlyActiveEmployees = new JCheckBox("Only active employees");
		allEmployeesCheckBoxOnlyActiveEmployees.setOpaque(false);
		allEmployeesCheckBoxOnlyActiveEmployees.setSelected(true);
		allEmployeesCheckBoxOnlyActiveEmployees.addActionListener(this);

		try
		{
			updateJobList();
			searchEmployees();
			updateJobs(allEmployeesComboBoxSearchJobs, true);
			GroupLayout gl_allEmployees = new GroupLayout(allEmployees);
			gl_allEmployees.setHorizontalGroup(
					gl_allEmployees.createParallelGroup(Alignment.LEADING)
					.addGroup(gl_allEmployees.createSequentialGroup()
							.addGap(10)
							.addComponent(allEmployeesLabelSearchJobs)
							.addGap(10)
							.addComponent(allEmployeesComboBoxSearchJobs, GroupLayout.PREFERRED_SIZE, 160, GroupLayout.PREFERRED_SIZE))
							.addGroup(gl_allEmployees.createSequentialGroup()
									.addGap(10)
									.addComponent(allEmployeesLabelSearchBy)
									.addGap(17)
									.addComponent(allEmployeesComboBoxSearchType, GroupLayout.PREFERRED_SIZE, 161, GroupLayout.PREFERRED_SIZE)
									.addGap(18)
									.addComponent(allEmployeesCheckBoxOnlyActiveEmployees))
									.addGroup(gl_allEmployees.createSequentialGroup()
											.addGap(10)
											.addComponent(allEmployeesLabelSearchFor)
											.addGap(15)
											.addComponent(allEmployeesTextFieldSearchFor, GroupLayout.PREFERRED_SIZE, 161, GroupLayout.PREFERRED_SIZE)
											.addGap(18)
											.addComponent(allEmployeesButtonSearchClear)
											.addGap(206)
											.addComponent(allEmployeesButtonEditEmployee)
											.addGap(10)
											.addComponent(allEmployeesButtonDeactivateEmployee))
											.addGroup(gl_allEmployees.createSequentialGroup()
													.addGap(10)
													.addComponent(allEmployeesTableScroll, GroupLayout.PREFERRED_SIZE, 769, GroupLayout.PREFERRED_SIZE))
													.addGroup(gl_allEmployees.createSequentialGroup()
															.addGap(635)
															.addComponent(label))
					);
			gl_allEmployees.setVerticalGroup(
					gl_allEmployees.createParallelGroup(Alignment.LEADING)
					.addGroup(gl_allEmployees.createSequentialGroup()
							.addGap(11)
							.addGroup(gl_allEmployees.createParallelGroup(Alignment.LEADING)
									.addGroup(gl_allEmployees.createSequentialGroup()
											.addGap(3)
											.addComponent(allEmployeesLabelSearchJobs))
											.addComponent(allEmployeesComboBoxSearchJobs, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))
											.addGap(5)
											.addGroup(gl_allEmployees.createParallelGroup(Alignment.LEADING)
													.addGroup(gl_allEmployees.createSequentialGroup()
															.addGap(4)
															.addComponent(allEmployeesLabelSearchBy))
															.addGroup(gl_allEmployees.createSequentialGroup()
																	.addGap(1)
																	.addComponent(allEmployeesComboBoxSearchType, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))
																	.addComponent(allEmployeesCheckBoxOnlyActiveEmployees))
																	.addGap(4)
																	.addGroup(gl_allEmployees.createParallelGroup(Alignment.LEADING)
																			.addGroup(gl_allEmployees.createSequentialGroup()
																					.addGap(4)
																					.addComponent(allEmployeesLabelSearchFor))
																					.addGroup(gl_allEmployees.createSequentialGroup()
																							.addGap(1)
																							.addComponent(allEmployeesTextFieldSearchFor, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))
																							.addComponent(allEmployeesButtonSearchClear)
																							.addComponent(allEmployeesButtonEditEmployee)
																							.addComponent(allEmployeesButtonDeactivateEmployee))
																							.addGap(11)
																							.addComponent(allEmployeesTableScroll, GroupLayout.PREFERRED_SIZE, 175, GroupLayout.PREFERRED_SIZE)
																							.addGap(57)
																							.addComponent(label))
					);
			allEmployees.setLayout(gl_allEmployees);
			updateJobs(newEmployeeComboBoxAccess, false);
			GroupLayout gl_newEmployee = new GroupLayout(newEmployee);
			gl_newEmployee.setHorizontalGroup(
					gl_newEmployee.createParallelGroup(Alignment.LEADING)
					.addGroup(gl_newEmployee.createSequentialGroup()
							.addGap(244)
							.addComponent(newEmployeeLabelName)
							.addGap(43)
							.addComponent(newEmployeeTextFieldUsername, GroupLayout.PREFERRED_SIZE, 156, GroupLayout.PREFERRED_SIZE))
							.addGroup(gl_newEmployee.createSequentialGroup()
									.addGap(244)
									.addComponent(newEmployeeLabelFirstName)
									.addGap(40)
									.addComponent(newEmployeeTextFieldFirstName, GroupLayout.PREFERRED_SIZE, 156, GroupLayout.PREFERRED_SIZE))
									.addGroup(gl_newEmployee.createSequentialGroup()
											.addGap(244)
											.addComponent(newEmployeeLabelLastName)
											.addGap(41)
											.addComponent(newEmployeeTextFieldLastName, GroupLayout.PREFERRED_SIZE, 156, GroupLayout.PREFERRED_SIZE))
											.addGroup(gl_newEmployee.createSequentialGroup()
													.addGap(244)
													.addComponent(newEmployeeLabelPassword)
													.addGap(45)
													.addComponent(newEmployeePasswordFieldFirst, GroupLayout.PREFERRED_SIZE, 156, GroupLayout.PREFERRED_SIZE))
													.addGroup(gl_newEmployee.createSequentialGroup()
															.addGap(244)
															.addComponent(newEmployeeLabelPasswordAgain)
															.addGap(15)
															.addComponent(newEmployeePasswordFieldSecond, GroupLayout.PREFERRED_SIZE, 156, GroupLayout.PREFERRED_SIZE))
															.addGroup(gl_newEmployee.createSequentialGroup()
																	.addGap(244)
																	.addComponent(newEmployeeLabelPhoneno)
																	.addGap(48)
																	.addComponent(newEmployeeTextFieldPhoneNo, GroupLayout.PREFERRED_SIZE, 156, GroupLayout.PREFERRED_SIZE))
																	.addGroup(gl_newEmployee.createSequentialGroup()
																			.addGap(244)
																			.addComponent(newEmployeeLabelEmail)
																			.addGap(63)
																			.addComponent(newEmployeeTextFieldEmail, GroupLayout.PREFERRED_SIZE, 156, GroupLayout.PREFERRED_SIZE))
																			.addGroup(gl_newEmployee.createSequentialGroup()
																					.addGap(244)
																					.addComponent(newEmployeeLabelStatus)
																					.addGap(60)
																					.addComponent(newEmployeeComboBoxStatus, GroupLayout.PREFERRED_SIZE, 156, GroupLayout.PREFERRED_SIZE))
																					.addGroup(gl_newEmployee.createSequentialGroup()
																							.addGap(244)
																							.addComponent(newEmployeeLabelAccess)
																							.addGap(58)
																							.addComponent(newEmployeeComboBoxAccess, GroupLayout.PREFERRED_SIZE, 156, GroupLayout.PREFERRED_SIZE))
																							.addGroup(gl_newEmployee.createSequentialGroup()
																									.addGap(388)
																									.addComponent(newEmployeeButtonCreateEmployee, GroupLayout.PREFERRED_SIZE, 156, GroupLayout.PREFERRED_SIZE))
					);
			gl_newEmployee.setVerticalGroup(
					gl_newEmployee.createParallelGroup(Alignment.LEADING)
					.addGroup(gl_newEmployee.createSequentialGroup()
							.addGap(11)
							.addGroup(gl_newEmployee.createParallelGroup(Alignment.LEADING)
									.addGroup(gl_newEmployee.createSequentialGroup()
											.addGap(3)
											.addComponent(newEmployeeLabelName))
											.addComponent(newEmployeeTextFieldUsername, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))
											.addGap(6)
											.addGroup(gl_newEmployee.createParallelGroup(Alignment.LEADING)
													.addGroup(gl_newEmployee.createSequentialGroup()
															.addGap(3)
															.addComponent(newEmployeeLabelFirstName))
															.addComponent(newEmployeeTextFieldFirstName, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))
															.addGap(6)
															.addGroup(gl_newEmployee.createParallelGroup(Alignment.LEADING)
																	.addGroup(gl_newEmployee.createSequentialGroup()
																			.addGap(3)
																			.addComponent(newEmployeeLabelLastName))
																			.addComponent(newEmployeeTextFieldLastName, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))
																			.addGap(8)
																			.addGroup(gl_newEmployee.createParallelGroup(Alignment.LEADING)
																					.addGroup(gl_newEmployee.createSequentialGroup()
																							.addGap(3)
																							.addComponent(newEmployeeLabelPassword))
																							.addComponent(newEmployeePasswordFieldFirst, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))
																							.addGap(6)
																							.addGroup(gl_newEmployee.createParallelGroup(Alignment.LEADING)
																									.addGroup(gl_newEmployee.createSequentialGroup()
																											.addGap(3)
																											.addComponent(newEmployeeLabelPasswordAgain))
																											.addComponent(newEmployeePasswordFieldSecond, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))
																											.addGap(6)
																											.addGroup(gl_newEmployee.createParallelGroup(Alignment.LEADING)
																													.addGroup(gl_newEmployee.createSequentialGroup()
																															.addGap(3)
																															.addComponent(newEmployeeLabelPhoneno))
																															.addComponent(newEmployeeTextFieldPhoneNo, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))
																															.addGap(6)
																															.addGroup(gl_newEmployee.createParallelGroup(Alignment.LEADING)
																																	.addGroup(gl_newEmployee.createSequentialGroup()
																																			.addGap(3)
																																			.addComponent(newEmployeeLabelEmail))
																																			.addComponent(newEmployeeTextFieldEmail, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))
																																			.addGap(6)
																																			.addGroup(gl_newEmployee.createParallelGroup(Alignment.LEADING)
																																					.addGroup(gl_newEmployee.createSequentialGroup()
																																							.addGap(3)
																																							.addComponent(newEmployeeLabelStatus))
																																							.addComponent(newEmployeeComboBoxStatus, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))
																																							.addGap(6)
																																							.addGroup(gl_newEmployee.createParallelGroup(Alignment.LEADING)
																																									.addGroup(gl_newEmployee.createSequentialGroup()
																																											.addGap(3)
																																											.addComponent(newEmployeeLabelAccess))
																																											.addComponent(newEmployeeComboBoxAccess, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))
																																											.addGap(6)
																																											.addComponent(newEmployeeButtonCreateEmployee))
					);
			newEmployee.setLayout(gl_newEmployee);

			btnPrint = new JButton();
			btnPrint.addActionListener(this);
			btnPrint.setText("Print");
			btnPrint.setOpaque(false);

			GroupLayout gl_redPanel = new GroupLayout(redPanel);
			gl_redPanel.setHorizontalGroup(
					gl_redPanel.createParallelGroup(Alignment.LEADING)
					.addGroup(gl_redPanel.createSequentialGroup()
							.addGap(10)
							.addComponent(redPanelLabelTitle, GroupLayout.PREFERRED_SIZE, 194, GroupLayout.PREFERRED_SIZE))
							.addComponent(tabbedPane, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
							.addGroup(gl_redPanel.createSequentialGroup()
									.addGap(8)
									.addComponent(btnBack, GroupLayout.PREFERRED_SIZE, 100, GroupLayout.PREFERRED_SIZE)
									.addGap(464)
									.addComponent(btnPrint, GroupLayout.PREFERRED_SIZE, 100, GroupLayout.PREFERRED_SIZE)
									.addPreferredGap(ComponentPlacement.UNRELATED)
									.addComponent(statistics, GroupLayout.PREFERRED_SIZE, 100, GroupLayout.PREFERRED_SIZE))
					);
			gl_redPanel.setVerticalGroup(
					gl_redPanel.createParallelGroup(Alignment.LEADING)
					.addGroup(gl_redPanel.createSequentialGroup()
							.addComponent(redPanelLabelTitle)
							.addGap(6)
							.addComponent(tabbedPane, GroupLayout.PREFERRED_SIZE, 309, GroupLayout.PREFERRED_SIZE)
							.addGap(4)
							.addGroup(gl_redPanel.createParallelGroup(Alignment.LEADING)
									.addComponent(btnBack, GroupLayout.PREFERRED_SIZE, 20, GroupLayout.PREFERRED_SIZE)
									.addGroup(gl_redPanel.createParallelGroup(Alignment.BASELINE)
											.addComponent(statistics, GroupLayout.PREFERRED_SIZE, 20, GroupLayout.PREFERRED_SIZE)
											.addComponent(btnPrint, GroupLayout.PREFERRED_SIZE, 20, GroupLayout.PREFERRED_SIZE))))
					);
			redPanel.setLayout(gl_redPanel);
		}
		catch (Exception e)
		{
			msgError(allEmployees, "Could not load properly");
		}
	}

	/**
	 *  Updates all the jobs into an arraylist
	 *  
	 *  @return void 
	 */
	private void updateJobList()
	{
		try
		{
			jobList = employeeCtrl.printAllEmployeeJobs();
		}
		catch (Exception e)
		{
			msgError(allEmployees, "Could not load jobs");
		}
	}

	/**
	 *  Updates a combo box with the jobs
	 *  
	 *  @param 	comboBox	the combo box which will be filled with information
	 *  @param	first		should it rather add a fake/empty first row or not
	 *  
	 *  @return void 
	 */
	private void updateJobs(JComboBox<String> comboBox, boolean first)
	{
		comboBox.removeAllItems();

		if (first)
			comboBox.addItem("All jobs");

		for(EmployeeJob job : jobList)
			comboBox.addItem(job.getJobName());
	}

	/**
	 * ActionPerformed.. where all the magic happens.
	 * Our listener for every action which happens.
	 * 
	 * @param 	e		the event which has triggered the listener
	 * @return 	void 
	 */
	@Override
	public void actionPerformed(ActionEvent e)
	{
		frameEmployeeUI.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));

		if (e.getSource() == allEmployeesCheckBoxOnlyActiveEmployees)
		{
			searchEmployees();
		}
		else if(e.getSource() == statistics)
		{
			StatisticsUI stats = StatisticsUI.getInstance();
			stats.display();
			frameEmployeeUI.setVisible(false);
		}
		else if (e.getSource() == allEmployeesButtonSearchClear)
		{
			allEmployeesComboBoxSearchType.setSelectedIndex(0);
			allEmployeesComboBoxSearchJobs.setSelectedIndex(0);
			allEmployeesTextFieldSearchFor.setText(null);

			searchEmployees();
		}
		else if (e.getSource() == allEmployeesComboBoxSearchJobs)
		{
			if (startup)
			{
				searchEmployees();
			}
		}
		else if (e.getSource() == allEmployeesComboBoxSearchType)
		{
			if (startup)
			{
				allEmployeesTextFieldSearchFor.setText(null);

				searchEmployees();
			}
		}
		else if (e.getSource() == allEmployeesButtonEditEmployee)
		{
			showEditEmployeeDialog();
		}
		else if (e.getSource() == newEmployeeButtonCreateEmployee)
		{
			addEmployee();
		}
		else if (e.getSource() == allEmployeesButtonDeactivateEmployee)
		{
			activateEmployee();
		}
		else if(e.getSource() == btnBack)
		{
			back.goBack(back.getNumber());
		}
		else if (e.getSource() == btnPrint)
		{
			printEmployeePDF();
		}

		frameEmployeeUI.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
	}

	private void printEmployeePDF()
	{
		if (allEmployeesTable.getRowCount() > 0)
		{
			ArrayList<ArrayList<String>> list = new ArrayList<ArrayList<String>>();
			String columns [] = { "#", "First Name", "Last Name", "PhoneNo", "Email", "Job", "Username", "Active" };

			ArrayList<String> employeeID = new ArrayList<String>();
			ArrayList<String> employeeFirstName = new ArrayList<String>();
			ArrayList<String> employeeLastName = new ArrayList<String>();
			ArrayList<String> employeePhoneNo = new ArrayList<String>();
			ArrayList<String> employeeEmail = new ArrayList<String>();
			ArrayList<String> employeeJob = new ArrayList<String>();
			ArrayList<String> employeeUsername = new ArrayList<String>();
			ArrayList<String> employeeActive = new ArrayList<String>();


			list.add(employeeID);
			list.add(employeeFirstName);
			list.add(employeeLastName);
			list.add(employeePhoneNo);
			list.add(employeeEmail);
			list.add(employeeJob);
			list.add(employeeUsername);
			list.add(employeeActive);

			for(int i = 0; i < allEmployeesTable.getRowCount(); i++)
			{
				list.get(0).add(String.valueOf(allEmployeesTable.getValueAt(i, 0)));
				list.get(1).add(String.valueOf(allEmployeesTable.getValueAt(i, 1)));
				list.get(2).add(String.valueOf(allEmployeesTable.getValueAt(i, 2)));
				list.get(3).add(String.valueOf(allEmployeesTable.getValueAt(i, 3)));
				list.get(4).add(String.valueOf(allEmployeesTable.getValueAt(i, 4)));
				list.get(5).add(String.valueOf(allEmployeesTable.getValueAt(i, 5)));
				list.get(6).add(String.valueOf(allEmployeesTable.getValueAt(i, 6)));
				list.get(7).add(String.valueOf(allEmployeesTable.getValueAt(i, 7)).contains("yes") ? "Yes" : "No");
			}

			PdfFilePrint pdfPrint = new PdfFilePrint();
			boolean successPDF = pdfPrint.PDFPrint("Employee", "Current Employees", "employee", "Nikola", columns, list);

			if(successPDF)
				msgSuccess(null, "PDF was created successfully");
			else
				msgError(null, "There was an error creating the PDF");
		}
		else
		{
			msgError(null, "Nothing to print");
		}
	}

	/**
	 * Necessary checks when adding an employee
	 * 
	 * @return	void
	 */
	private void addEmployee()
	{
		boolean validInfo = employeeCheckValidInfo(newEmployeeTextFields, newEmployeePasswordFields, true);
		boolean validPassword = employeeCheckValidPassword(newEmployeePasswordFieldFirst, newEmployeePasswordFieldSecond);
		boolean validEmail = emailValidator.validate(newEmployeeTextFieldEmail.getText());

		if (validInfo && validPassword && validEmail)
		{
			try
			{
				int success = employeeCtrl.createEmployee(newEmployeeTextFieldFirstName.getText(), newEmployeeTextFieldLastName.getText(), newEmployeeTextFieldEmail.getText(), newEmployeeTextFieldPhoneNo.getText(), newEmployeeTextFieldUsername.getText(), new String(newEmployeePasswordFieldFirst.getPassword()), (newEmployeeComboBoxStatus.getSelectedIndex() == 0), employeeCtrl.findEmployeeJobByName(newEmployeeComboBoxAccess.getSelectedItem().toString()));

				if (success > 0)
				{
					msgSuccess(newEmployee, "Employee \"" + newEmployeeTextFieldUsername.getText() + "\" has been added successfully");

					for(JTextField tf : newEmployeeTextFields)
						tf.setText(null);

					for (JPasswordField pf : newEmployeePasswordFields)
						pf.setText(null);					

					searchEmployees();
				}
				else
				{
					msgError(newEmployee, "There was an error adding the employee.\nThis username already exists in the system.");					
				}
			}
			catch (Exception ex)
			{
				msgError(newEmployee, "There was an error adding the employee.");
			}
		}
		else 
		{
			String error = "You cannot proceed due some errors:\n\n";

			if (!validInfo)
				error += " - You haven't filled up every text area or a field has more than 32 symbols\n";

			if (!validPassword)
				error += " - The two passwords do not match\n";	

			if (!validEmail)
				error += " - Email is not valid\n";

			msgError(newEmployee, error);
		}
	}

	/**
	 * Necessary checks (and dialog opening) when editing an employee
	 * 
	 * @return	void
	 */
	private void showEditEmployeeDialog()
	{
		if (allEmployeesTable.getSelectedRow() > -1) 
		{
			try
			{
				int employeeID = Integer.valueOf(String.valueOf(allEmployeesTable.getValueAt(allEmployeesTable.getSelectedRow(), 0)));
				Employee editEmployee = employeeCtrl.searchEmployeeID(employeeID);

				JPanel panel = new JPanel(new GridLayout(0, 2, 5, 5));

				JTextField editEmployeeTextFieldEmployeeUsername = new JTextField(editEmployee.getUsername());
				JTextField editEmployeeTextFieldEmployeeFirstName = new JTextField(editEmployee.getfName());
				JTextField editEmployeeTextFieldEmployeeSecondName = new JTextField(editEmployee.getlName());
				JTextField editEmployeeTextFieldEmployeePhoneNo = new JTextField(editEmployee.getPhoneNo());
				JTextField editEmployeeTextFieldEmployeeEmail = new JTextField(editEmployee.getEmail());

				JPasswordField editEmployeePasswordFieldFirst = new JPasswordField(null);
				JPasswordField editEmployeePasswordFieldSecond = new JPasswordField(null);

				JComboBox<String> editEmployeeComboBoxStatus = new JComboBox<String>();
				editEmployeeComboBoxStatus.addItem("Active");
				editEmployeeComboBoxStatus.addItem("Inactive");
				editEmployeeComboBoxStatus.setSelectedIndex(editEmployee.isActive() ? 0 : 1);

				editEmployeeComboBoxAccess = new JComboBox<String>();

				updateJobs(editEmployeeComboBoxAccess, false);
				editEmployeeComboBoxAccess.setSelectedItem(editEmployee.getJob().getJobName());

				panel.add(new JLabel("Employee Username:"));
				panel.add(editEmployeeTextFieldEmployeeUsername);
				panel.add(new JLabel("Employee First Name:"));
				panel.add(editEmployeeTextFieldEmployeeFirstName);
				panel.add(new JLabel("Employee Second Name:"));
				panel.add(editEmployeeTextFieldEmployeeSecondName);
				panel.add(new JLabel("Employee Password:"));
				panel.add(editEmployeePasswordFieldFirst);
				panel.add(new JLabel("Employee Password Again:"));
				panel.add(editEmployeePasswordFieldSecond);
				panel.add(new JLabel("Employee PhoneNo:"));
				panel.add(editEmployeeTextFieldEmployeePhoneNo);
				panel.add(new JLabel("Employee E-mail:"));
				panel.add(editEmployeeTextFieldEmployeeEmail);
				panel.add(new JLabel("Employee Status:"));
				panel.add(editEmployeeComboBoxStatus);
				panel.add(new JLabel("Employee Access:"));
				panel.add(editEmployeeComboBoxAccess);

				editEmployeeTextFields = new ArrayList<JTextField>();
				editEmployeeTextFields.add(editEmployeeTextFieldEmployeeUsername);
				editEmployeeTextFields.add(editEmployeeTextFieldEmployeePhoneNo);
				editEmployeeTextFields.add(editEmployeeTextFieldEmployeeEmail);

				editEmployeePasswordFields = new ArrayList<JPasswordField>();
				editEmployeePasswordFields.add(editEmployeePasswordFieldFirst);
				editEmployeePasswordFields.add(editEmployeePasswordFieldSecond);

				int option = JOptionPane.showConfirmDialog(allEmployees, panel, "Edit employee", JOptionPane.OK_CANCEL_OPTION);

				if (option == JOptionPane.YES_OPTION)
				{
					boolean validInfo = employeeCheckValidInfo(editEmployeeTextFields, editEmployeePasswordFields, false);
					boolean validPassword = employeeCheckValidPassword(editEmployeePasswordFieldFirst, editEmployeePasswordFieldSecond);
					boolean validEmail = emailValidator.validate(editEmployeeTextFieldEmployeeEmail.getText());

					if (validInfo && validPassword && validEmail)
					{
						String password = editEmployeePasswordFieldFirst.getPassword().length > 0 ? MD5.md5(new String(editEmployeePasswordFieldFirst.getPassword())) : editEmployee.getPassword();

						int success = employeeCtrl.updateEmployee(employeeID, editEmployeeTextFieldEmployeeFirstName.getText(), editEmployeeTextFieldEmployeeSecondName.getText(), editEmployeeTextFieldEmployeeEmail.getText(), editEmployeeTextFieldEmployeePhoneNo.getText(), editEmployeeTextFieldEmployeeUsername.getText(), password, (editEmployeeComboBoxStatus.getSelectedIndex() == 0), employeeCtrl.findEmployeeJobByName(editEmployeeComboBoxAccess.getSelectedItem().toString()));

						if (success > 0)
						{
							msgSuccess(newEmployee, "Employee #" + employeeID + " has been edited successfully");
							searchEmployees();
						}
						else 
						{
							msgError(newEmployee, "There was an error editing the employee");
						}
					}
					else 
					{
						String error = "You cannot proceed due some errors:\n\n";

						if (!validInfo)
							error += " - You haven't filled up every text area\n";

						if (!validPassword)
							error += " - The two passwords do not match\n";	

						if (!validEmail)
							error += " - Email is not valid\n";

						msgError(newEmployee, error);
					}
				}
			}
			catch (SQLException | NoSuchAlgorithmException ex)
			{
				msgError(allEmployees, "There was a problem loading the employee");
			}
		}
		else 
		{
			msgError(allEmployees, "You have not selected an employee");
		}
	}

	/**
	 * Returns if the two ArrayLists which are given are not empty or the length
	 * is more than 32 symbols.
	 *
	 * @param  	textFields 			an array list with all the text fields which need to be checked
	 * @param  	passwordFields		an array list with all the password fields which need to be checked
	 * @param	checkPass			if it will check the password or not
	 * 
	 * @return	true 				if they are not empty
	 */
	private boolean employeeCheckValidInfo(ArrayList<JTextField> textFields, ArrayList<JPasswordField> passwordFields, boolean checkPass)
	{
		for(JTextField tf : textFields)
		{
			if ((tf.getText().trim().length() == 0) || (tf.getText().length() > 32))
				return false;
		}

		if (checkPass)
		{
			for(JPasswordField pf : passwordFields)
			{
				if (pf.getPassword().length == 0)
					return false;
			}
		}

		return true;
	}

	/**
	 * Checks if two password fields are equal
	 *
	 * @param  	passwordFieldFirst		password field one
	 * @param  	passwordFieldSecond 	password field two
	 * 
	 * @return	true					if they are the same
	 */
	private boolean employeeCheckValidPassword(JPasswordField passwordFieldFirst, JPasswordField passwordFieldSecond)
	{
		if (!Arrays.equals(passwordFieldFirst.getPassword(), passwordFieldSecond.getPassword()))
			return false;

		return true;
	}


	/**
	 * Updating the all employees table
	 *
	 * @param  	employeeList	the array list which is put in the table
	 * 
	 * @return	void
	 */
	private void allEmployeesUpdateTable(ArrayList<Employee> employeeList)
	{
		if (employeeList.size() > 0)
		{
			tableClearList();

			for(Employee employee : employeeList)
			{
				allEmployeesTableModel.addRow(
						new Object[]
								{ 
								employee.getPersonID(), 
								employee.getfName(),
								employee.getlName(),
								employee.getPhoneNo(),
								employee.getEmail(),
								employee.getJob().getJobName(),
								employee.getUsername(),
								new ImageIcon("img/tick_" + (employee.isActive() ? "yes" : "no") + ".png")
								} 
						);
			}
		}
	}

	/**
	 * Removing all rows from the all employee table
	 *
	 * @return	void
	 */
	private void tableClearList()
	{
		DefaultTableModel dm = (DefaultTableModel) allEmployeesTable.getModel();

		while(dm.getRowCount() > 0)
			dm.removeRow(0);
	}

	/**
	 * Activating/deactivating an employee
	 *
	 * @return	void
	 */
	public void activateEmployee()
	{
		DefaultTableModel model = (DefaultTableModel) allEmployeesTable.getModel();
		int[] rows = allEmployeesTable.getSelectedRows();

		for (int i = 0; i < rows.length; i++)
		{
			int employeeID = Integer.valueOf((String.valueOf(model.getValueAt(rows[i]-i,0))));

			try
			{
				if (employeeCtrl.activateEmployee(employeeID) > 0)
				{
					msgSuccess(allEmployees, "Successfully changed " + String.valueOf(model.getValueAt(rows[i]-i,1)) + "'s status");

					searchEmployees();
				}
			}
			catch (SQLException e)
			{
				msgError(allEmployees, "There was an error changing \"" + String.valueOf(model.getValueAt(rows[i]-i,1)) + "'s status");
			}
		}
	}

	/**
	 * Searching employee based on the selected drop down criteria 
	 * and input text field
	 * 
	 * @return	void
	 */
	private void searchEmployees()
	{
		ArrayList<Employee> employeeList = new ArrayList<Employee>();

		String clause = allEmployeesComboBoxSearchType.getSelectedItem().toString().toLowerCase();
		String search = allEmployeesTextFieldSearchFor.getText();

		try
		{
			boolean active = allEmployeesCheckBoxOnlyActiveEmployees.isSelected();

			String jobName = allEmployeesComboBoxSearchJobs.getItemCount() > 0 ? (allEmployeesComboBoxSearchJobs.getSelectedIndex() == 0 ? "" : allEmployeesComboBoxSearchJobs.getSelectedItem().toString()) : "";

			switch (clause)
			{
				case "email": 		employeeList = employeeCtrl.searchEmployeeEmail(active, jobName , search); break;
				case "phoneno":		employeeList = employeeCtrl.searchEmployeePhoneNo(active, jobName, search); break;
				case "username":	employeeList = employeeCtrl.searchEmployeeUsername(active, jobName, search); break;
				case "name":		employeeList = employeeCtrl.searchEmployeeName(active, jobName, search); break;
				case "everything":	employeeList = employeeCtrl.searchEmployeeEverything(active, jobName, search); break;
			}

			if (employeeList.size() > 0)
				allEmployeesUpdateTable(employeeList);
			else
				tableClearList();
		}
		catch (Exception e)
		{
			msgError(allEmployees, "Could not load employees");
		}

		if (!startup)
			startup = true;
	}

	/**
	 * Shows an error message pop-up
	 * 
	 * @param	panel 		on which panel should it show the message
	 * @param	error		the error which is printed on the pop-up window
	 * 
	 * @return	void
	 */
	private void msgError(JPanel panel, String error)
	{
		JOptionPane.showConfirmDialog(panel, error, "Error", JOptionPane.PLAIN_MESSAGE, JOptionPane.ERROR_MESSAGE);
	}

	/**
	 * Shows a success message pop-up
	 * 
	 * @param	panel 		on which panel should it show the message
	 * @param	success		the success message which is printed on the pop-up window
	 * 
	 * @return	void
	 */
	private void msgSuccess(JPanel panel, String success)
	{
		JOptionPane.showMessageDialog(panel, success, "Success", 1);
	}

	public static EmployeeUI getInstance()
	{
		if(instance == null)
			instance = new EmployeeUI();

		return instance;			
	}

	public static void main(String[] args)
	{
		try 
		{
			UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 

			EmployeeUI employeeMenu = new EmployeeUI();
			employeeMenu.display();
		}
		catch(Exception e)
		{
			JOptionPane.showMessageDialog(null, "Employee Menu could not load");
		}
	}
}